package com.psedu.exam.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.psedu.exam.constant.Constants;
import com.psedu.exam.domain.Exam;
import com.psedu.exam.domain.vo.DeptExamDateUpdateVo;
import com.psedu.exam.domain.vo.DeptExamVo;
import com.psedu.exam.mapper.ExamMapper;
import com.psedu.common.core.constant.SecurityConstants;
import com.psedu.common.core.domain.R;
import com.psedu.common.core.exception.ServiceException;
import com.psedu.common.core.utils.DateUtils;
import com.psedu.system.api.RemoteDeptService;
import com.psedu.system.api.domain.vo.SysSimpleDeptVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.psedu.exam.mapper.ExamDeptStatusMapper;
import com.psedu.exam.domain.ExamDeptStatus;
import com.psedu.exam.service.IExamDeptStatusService;

/**
 * 分党校考试信息Service业务层处理
 * 
 * @author mingyue
 * @date 2022-03-30
 */
@Service
public class ExamDeptStatusServiceImpl implements IExamDeptStatusService 
{
    @Autowired
    private ExamDeptStatusMapper examDeptStatusMapper;

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private RemoteDeptService remoteDeptService;

    /**
     * 查询分党校考试信息
     * 
     * @param examDeptStatusId 分党校考试信息主键
     * @return 分党校考试信息
     */
    @Override
    public ExamDeptStatus selectExamDeptStatusByExamDeptStatusId(Long examDeptStatusId)
    {
        return examDeptStatusMapper.selectById(examDeptStatusId);
    }

    /**
     * 查询分党校考试信息列表
     * 
     * @param examDeptStatus 分党校考试信息
     * @return 分党校考试信息
     */
    @Override
    public List<ExamDeptStatus> selectExamDeptStatusList(ExamDeptStatus examDeptStatus)
    {
        return examDeptStatusMapper.selectExamDeptStatusList(examDeptStatus);
    }

    /**
     * 新增分党校考试信息
     * 
     * @param examDeptStatus 分党校考试信息
     * @return 结果
     */
    @Override
    public int insertExamDeptStatus(ExamDeptStatus examDeptStatus)
    {
        examDeptStatus.setCreateTime(DateUtils.getNowDate());
        return examDeptStatusMapper.insert(examDeptStatus);
    }

    /**
     * 修改分党校考试信息
     * 
     * @param examDeptStatus 分党校考试信息
     * @return 结果
     */
    @Override
    public int updateExamDeptStatus(ExamDeptStatus examDeptStatus)
    {
        return examDeptStatusMapper.updateById(examDeptStatus);
    }

    /**
     * 批量删除分党校考试信息
     * 
     * @param examDeptStatusIds 需要删除的分党校考试信息主键
     * @return 结果
     */
    @Override
    public int deleteExamDeptStatusByExamDeptStatusIds(Long[] examDeptStatusIds)
    {
        return examDeptStatusMapper.deleteBatchIds(Arrays.asList(examDeptStatusIds));
    }

    /**
     * 删除分党校考试信息信息
     * 
     * @param examDeptStatusId 分党校考试信息主键
     * @return 结果
     */
    @Override
    public int deleteExamDeptStatusByExamDeptStatusId(Long examDeptStatusId)
    {
        return examDeptStatusMapper.deleteById(examDeptStatusId);
    }

    /**
     * 获取部门考试视图
     * @param examId 考试Id
     * @param deptId 部门ID
     * @return 部门考试信息视图
     */
    @Override
    public List<DeptExamVo> deptExamView(Long examId, Long deptId) {
        LambdaQueryWrapper<ExamDeptStatus> statusLambdaQueryWrapper = new LambdaQueryWrapper<ExamDeptStatus>()
                .eq(ExamDeptStatus::getExamId, examId);
        if(deptId != null) {
            statusLambdaQueryWrapper.eq(ExamDeptStatus::getDeptId, deptId);
        }
        List<ExamDeptStatus> examDeptStatusList = examDeptStatusMapper.selectList(
                statusLambdaQueryWrapper
        );
        // 分离出部门
        List<Long> deptIdList = examDeptStatusList.stream()
                .map(ExamDeptStatus::getDeptId)
                .distinct()
                .collect(Collectors.toList());
        R<List<SysSimpleDeptVo>> deptNameListR = remoteDeptService.getDeptNameByDeptId(deptIdList, SecurityConstants.INNER);
        List<SysSimpleDeptVo> sysSimpleDeptVoList = deptNameListR.getData();
        Map<Long, String> deptMap = sysSimpleDeptVoList.stream().collect(Collectors.toMap(SysSimpleDeptVo::getDeptId, SysSimpleDeptVo::getDeptName));
        // 再循环，部门填充进入vo
        // vo放入list
        List<DeptExamVo> deptExamVos = new ArrayList<>();
        for (Long nowDeptId : deptIdList) {
            DeptExamVo deptExamVoCell = new DeptExamVo();
            deptExamVos.add(deptExamVoCell);
            deptExamVoCell.setDeptId(nowDeptId);
            // 当前部门考试包含的所有考试列表
            List<ExamDeptStatus> nowExamDeptStatusList = examDeptStatusList.stream()
                    .filter(examDeptStatus -> nowDeptId.equals(examDeptStatus.getDeptId()))
                    .sorted(Comparator.comparingInt(ExamDeptStatus::getRepeatCount))
                    .collect(Collectors.toList());
            deptExamVoCell.setUnderway(false);
            System.out.println(nowExamDeptStatusList);
            nowExamDeptStatusList.forEach(examDeptStatus -> {
                if(examDeptStatus != null && examDeptStatus.getStatus() != null && examDeptStatus.getStatus() == 1) {
                    deptExamVoCell.setUnderway(true);
                }
            });
            deptExamVoCell.setExamDeptStatusList(nowExamDeptStatusList);
            deptExamVoCell.setDeptName(deptMap.getOrDefault(nowDeptId, "部门不存在"));
        }
        // 统一考试信息
        Exam exam = examMapper.selectById(examId);
        deptExamVos.forEach(deptExamVoCell -> {
            deptExamVoCell.setTotalTime(exam.getTotalTime());
        });
        return deptExamVos;
    }

    @Override
    public int updateStartTime(DeptExamDateUpdateVo deptExamDateUpdateVo) {
        // TODO 非法修改，权限、考试已经开始
        Long totalTime = getExamTotalTimeByExamDeptId( deptExamDateUpdateVo.getExamDeptStatusId() );
        // 填充更新数据
        ExamDeptStatus updateExamDeptStatus = new ExamDeptStatus();
        updateExamDeptStatus.setExamDeptStatusId( deptExamDateUpdateVo.getExamDeptStatusId() );
        updateExamDeptStatus.setStartTime( deptExamDateUpdateVo.getStartTime() );
        DateTime endTime = DateUtil.offsetMinute(deptExamDateUpdateVo.getStartTime(), totalTime.intValue());
        updateExamDeptStatus.setEndTime(endTime);

        return examDeptStatusMapper.updateById(updateExamDeptStatus);
    }

    @Override
    public ExamDeptStatus nextStatus(Long examDeptStatusId) {
        ExamDeptStatus updateExamDeptStatus = examDeptStatusMapper.selectById(examDeptStatusId);
        updateExamDeptStatus.setExamDeptStatusId(examDeptStatusId);

        // 只能同时有一个运行中
        Long examId = updateExamDeptStatus.getExamId();
        Long deptId = updateExamDeptStatus.getDeptId();
        List<ExamDeptStatus> examDeptStatuses = examDeptStatusMapper.selectList(
                new LambdaQueryWrapper<ExamDeptStatus>()
                        .eq(ExamDeptStatus::getExamId, examId)
                        .eq(ExamDeptStatus::getDeptId, deptId)
        );
        for (ExamDeptStatus examDeptStatus : examDeptStatuses) {
            if( otherDeptExamRunning(examDeptStatusId, examDeptStatus) ) {
                throw new ServiceException("分党校不可同时开启两轮考试");
            }
        }

        // 下一考试状态，TODO，按时关闭考试。
        int nextStatus = 0;
        if( Constants.DEPT_EXAM_END == updateExamDeptStatus.getStatus()) {
            throw new ServiceException("考试已结束，不可修改");
        }
        if (Constants.DEPT_EXAM_WAIT == updateExamDeptStatus.getStatus()) {
            nextStatus = Constants.DEPT_EXAM_RUNNING;
        } else if (Constants.DEPT_EXAM_RUNNING == updateExamDeptStatus.getStatus()) {
            nextStatus = Constants.DEPT_EXAM_END;
        }
        updateExamDeptStatus.setStatus( nextStatus );

        // 考试时间调整
        if( Constants.DEPT_EXAM_RUNNING == nextStatus ) {
            updateExamDeptStatus.setStartTime( new Date() );
            Date startTime = updateExamDeptStatus.getStartTime();
            Long totalTime = getExamTotalTimeByExamDeptId( examDeptStatusId );
            DateTime endTime = DateUtil.offsetMinute(startTime, totalTime.intValue());
            updateExamDeptStatus.setEndTime(endTime);
        } else if( Constants.DEPT_EXAM_END == nextStatus ) {
            updateExamDeptStatus.setEndTime( new Date() );
        }
        examDeptStatusMapper.updateById( updateExamDeptStatus );
        return updateExamDeptStatus;
    }

    private boolean otherDeptExamRunning(Long examDeptStatusId, ExamDeptStatus examDeptStatus) {
        return Constants.DEPT_EXAM_RUNNING == examDeptStatus.getStatus()
                && !examDeptStatus.getExamDeptStatusId().equals(examDeptStatusId);
    }

    private Long getExamTotalTimeByExamDeptId(Long examDeptStatusId) {
        // 通过分党校考试信息获取考试时长
        ExamDeptStatus examDeptStatus = examDeptStatusMapper.selectById(examDeptStatusId);
        Long examId = examDeptStatus.getExamId();
        Exam exam = examMapper.selectById(examId);
        return exam.getTotalTime();
    }
}
